# @Version        : 1.0
# @Update Time    : 2024/11/7 22:16
# @File           : monitor_controller.py
# @IDE            : PyCharm
# @Desc           : 服务监控API
import json
from fastapi import APIRouter, Depends
from fastapi.concurrency import run_in_threadpool
from fastapi_utils.cbv import cbv
from pyecharts import options as opts
from pyecharts.charts import Gauge, Pie

from authx.dependencies.auth import RequireLogin
from src.core.base_controller import BaseController
from src.core.response.response_schema import ResponseGenericSchema
from src.schemas.user_info_schema import UserInfo
from src.db.db_redis import get_redis_dependency, AsyncRedisTool
from src.schemas.monitor_schema import ServerMonitorModel, CacheMonitorModel
from src.services.monitor_service import MonitorService
from src.utils.toolsutils import ToolsUtils

router = APIRouter()


@cbv(router)
class MonitorController(BaseController):
    """
    服务监控API
    """

    login_id: UserInfo = Depends(RequireLogin())

    @router.get(
        "/server",
        summary="获取服务器监控信息",
        response_model=ResponseGenericSchema[ServerMonitorModel],
    )
    async def get_server_monitor_info(self):
        """
        获取服务器监控信息
        """
        monitor_service = MonitorService()
        monitor_info = await monitor_service.get_monitor_info()
        return self.success(data=monitor_info)

    # 查询磁盘仪表盘仪表盘
    @router.get(
        "/cache/gauge",
        summary="获取磁盘信息",
        response_model=ResponseGenericSchema[dict],
    )
    async def get_mem_gauge_chart(
        self,
        db: AsyncRedisTool = Depends(get_redis_dependency),
    ):
        """
        获取磁盘信息
        """
        info = await db.client.info()
        used_memory_human = info.get("used_memory_human")
        # used_memory_human根据单位转成字节
        size = ToolsUtils.human2bytes(used_memory_human)
        # 转成MB
        used_mem_size = size / 1024 / 1024
        # 将单位转换成M
        c = (
            Gauge()
            .add(
                "内存占用",
                [("内存占用", round(used_mem_size, 2))],  # noqa
                split_number=5,
                axisline_opts=opts.AxisLineOpts(
                    linestyle_opts=opts.LineStyleOpts(
                        color=[(0.3, "#67e0e3"), (0.7, "#37a2da"), (1, "#fd666d")],
                        width=30,
                    )
                ),
                detail_label_opts=opts.GaugeDetailOpts(formatter="{value}M"),
            )
            .set_global_opts(
                legend_opts=opts.LegendOpts(is_show=False),
            )
        )
        return self.success(data=json.loads(c.dump_options()))

    # redis命令饼状图
    @router.get(
        "/cache/pie",
        summary="获取redis命令饼状图",
        response_model=ResponseGenericSchema[dict],
    )
    async def get_redis_pie_chart(
        self,
        db: AsyncRedisTool = Depends(get_redis_dependency),
    ):
        """
        获取redis命令饼状图
        """
        command_stats_dict = await db.client.info("commandstats")
        # command_stats = [
        #     dict(name=key.split('_')[1], value=str(value.get('calls'))) for key, value in command_stats_dict.items()
        # ]
        command_stats = [
            [key.split("_")[1], int(value.get("calls"))]
            for key, value in command_stats_dict.items()
        ]
        c = (
            Pie()
            .add(
                "",
                command_stats,
                center=["40%", "50%"],
                radius=["30%", "75%"],
                rosetype="radius",
                label_opts=opts.LabelOpts(is_show=False),
            )
            .set_global_opts(
                legend_opts=opts.LegendOpts(
                    type_="scroll", pos_left="80%", orient="vertical"
                ),
            )
            .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
        )
        return self.success(data=json.loads(c.dump_options()))

    @router.get(
        "/cache/info",
        summary="获取redis缓存信息",
        response_model=ResponseGenericSchema[CacheMonitorModel],
    )
    async def get_cache_info(
        self,
        db: AsyncRedisTool = Depends(get_redis_dependency),
    ):
        info = await db.client.info()
        # uptime_in_days: 运行天数，redis_version: 版本号，used_memory_human: 内存使用情况，
        # keys: key数量, db_size: key数量, aof_enabled:AOF是否开启, RDB是否成功: rdb_last_bgsave_status, 端口: tcp_port,
        # used_cpu_user_children: cpu使用情况, 网络入口/出口: total_net_input_bytes, total_net_output_bytes,
        # maxmemory_human: 最大内存,redis_mode: 集群模式,connected_clients: 连接数
        # 返回上诉配置,
        res = {
            "uptime_in_days": info.get("uptime_in_days"),
            "redis_version": info.get("redis_version"),
            "used_memory_human": info.get("used_memory_human"),
            "aof_enabled": "是" if info.get("aof_enabled") == 1 else "否",
            "rdb_last_bgsave_status": info.get("rdb_last_bgsave_status"),
            "tcp_port": info.get("tcp_port"),
            "used_cpu_user_children": info.get("used_cpu_user_children"),
            "instantaneous_input_kbps": info.get("instantaneous_input_kbps"),
            "instantaneous_output_kbps": info.get("instantaneous_output_kbps"),
            "maxmemory_human": info.get("maxmemory_human"),
            "redis_mode": "单机" if info.get("redis_mode") == "standalone" else "集群",
            "connected_clients": info.get("connected_clients"),
        }
        db_size = await db.client.dbsize()
        # print(info, db_size)
        # command_stats_dict = await db.info('commandstats')
        # command_stats = [
        #     dict(name=key.split('_')[1], value=str(value.get('calls'))) for key, value in command_stats_dict.items()
        # ]
        result = CacheMonitorModel(info=res, db_size=db_size)
        return self.success(data=result)
